package com.study.chunguard.common.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.study.chunguard.common.exception.BusinessException;
import com.study.chunguard.common.exception.code.ResponseCode;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Objects;

/**
 * 响应包装体
 *
 * @author zhaowenhao
 * @since 2022-12-27
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {

    private T data;
    private Integer code;
    private String msg;

    public static <T> Result<T> ok() {
        return of(null, ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg());
    }

    public static <T> Result<T> ok(T data) {
        return of(data, ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg());
    }

    public static <T> Result<T> ok(T data, String msg) {
        return of(data, ResponseCode.SUCCESS.getCode(), msg);
    }

    public static <T> Result<T> fail() {
        return of(null, ResponseCode.FAIL.getCode(), ResponseCode.FAIL.getMsg());
    }

    public static <T> Result<T> fail(String msg) {
        return of(null, ResponseCode.FAIL.getCode(), msg);
    }

    public static <T> Result<T> fail(int code, String msg) {
        return of(null, code, msg);
    }

    public static <T> Result<T> fail(ResponseCode responseCode) {
        return of(null, responseCode.getCode(), responseCode.getMsg());
    }

    public static <T> Result<T> of(T data, int code, String msg) {
        return new Result<>(data, code, msg);
    }

    /**
     * 判断是否成功
     *
     * @param code 状态码
     * @return 是否成功
     */
    public static boolean isSuccess(Integer code) {
        return Objects.equals(code, ResponseCode.SUCCESS.getCode());
    }

    /**
     * 判断是否成功
     *
     * @return 是否成功
     */
    @JsonIgnore
    public boolean isSuccess() {
        return isSuccess(code);
    }

    @JsonIgnore
    public boolean isError() {
        return !isSuccess();
    }

    // ========= 和 Exception 异常体系集成 =========

    /**
     * 判断是否有异常。如果有，则抛出 {@link BusinessException} 异常
     */
    public void checkError() throws BusinessException {
        if (isSuccess()) {
            return;
        }
        // 业务异常
        throw new BusinessException(code, msg);
    }

    /**
     * 判断是否有异常。如果有，则抛出 {@link BusinessException} 异常
     * 如果没有，则返回 {@link #data} 数据
     */
    @JsonIgnore
    public T getCheckedData() {
        checkError();
        return data;
    }
}
